package com.jince.datacenter.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.MalformedServerReplyException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.jince.datacenter.Constants;

/**
 * FTP工具类
 *
 */
public class FTPUtil {

	/**
	 * 日志
	 */
	private final static Logger logger = Logger.getLogger(FTPUtil.class);

	/**
	 * 
	 * @param ip
	 * @param username
	 * @param password
	 * @return
	 */
	public static FTPClient getFTPClient(String ip, String username,
			String password) {

		FTPClient ftpClient = null;
		try {
			// FTP配置
			logger.info("FTP地址：" + ip + "，账号：" + username + "，密码：" + password);
			ftpClient = new FTPClient();
			// ftpClient.setConnectTimeout(timeout);
			ftpClient.connect(ip);
			ftpClient.login(username, password);
			ftpClient.setControlEncoding(Constants.ENCODE_UTF8); // 中文支持
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftpClient.setKeepAlive(true);

			// 判断FTP账号密码是否正确
			if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
				logger.error("FTP未连接，用户名或密码错误...");
				ftpClient.disconnect();
				ftpClient = null;
			} else {
				logger.info("FTP连接成功...");
			}
		} catch (SocketException e) {
			logger.error("FTP连接异常：" + e);
			ftpClient = null;
		} catch (IOException e) {
			logger.error("FTP连接异常：" + e);
			ftpClient = null;
		}
		return ftpClient;
	}

	/**
	 * 关闭FTP连接
	 * 
	 * @param ftpClient
	 */
	public static void closeFTPClient(FTPClient ftpClient) {

		if (null != ftpClient) {
			try {
				// 判断当前FTP实例是否正常连接
				if (!ftpClient.isConnected())
					return;
				try {
					boolean logoutFlag = ftpClient.logout();
					if (logoutFlag)
						logger.info("FTP登出成功...");
				} finally {
					ftpClient.disconnect();
					logger.info("FTP连接关闭成功...");
				}
			} catch (IOException e) {
				logger.error("FTP关闭异常：" + e);
			}
		}
	}

	/**
	 * FTP文件下载
	 * 
	 * @param ftpClient
	 *            FTP实例
	 * @param remoteFileList
	 *            待获取的FTP文件列表
	 * @param localPath
	 *            待储存的本地路径
	 */
	public static void bathDownload(FTPClient ftpClient,
			List<String> remoteFileList, String localPath) throws Exception {

		// 判断FTP实例是否存在
		if (null == ftpClient) {
			logger.error("无FTP实例...");
			return;
		}

		// 判断文件参数是否为空
		if (null == remoteFileList || remoteFileList.size() < 1) {
			logger.error("待下载的文件列表为空...");
			return;
		}

		// 判断本地存储路径是否为空
		if (StringUtils.isEmpty(localPath)) {
			logger.error("本地存储路径为空...");
			return;
		}

		// 判断路径是否存在
		File path = new File(localPath);
		if (!path.exists()) {
			logger.info("构建当日目录：" + path);
			path.mkdirs();
		}

		// 输出流
		OutputStream output = null;
		// 循环下载
		for (String remoteFileName : remoteFileList) {

			try {
				// 获取FTP文件
				FTPFile[] remoteFiles = ftpClient.listFiles(remoteFileName);
				if (null != remoteFiles && remoteFiles.length > 0) {
					// 获取文件
					FTPFile remoteFile = remoteFiles[0];
					if (!remoteFile.isFile()) {
						logger.info("文件" + remoteFile.getName() + "不是文件...");
						continue;
					}
					// 本地文件
					String fileName = localPath + File.separator
							+ remoteFile.getName();
					// 构建本地文件
					File localFile = new File(fileName);
					if (localFile.exists()) {
						logger.info("文件：" + fileName + "已经存在！");
						continue;
					}
					// 构建输出流
					output = new FileOutputStream(localFile);
					// 文件传输
					ftpClient.retrieveFile(remoteFileName, output);
				}

			} catch (Exception e) {
				logger.error(e);
				continue;
			}
		}

		if (null != output)
			output.close();
	}

	/**
	 * FTP文件下载
	 * 
	 * @param ftpClient
	 *            FTP实例
	 * @param remotePath
	 *            待获取的FTP文件路径
	 * @param localPath
	 *            待储存的本地路径
	 * @return
	 */
	public static boolean bathDownload(FTPClient ftpClient, String remotePath,
			String localPath) {

		// 返回对象，默认false
		boolean flag = true;

		// 判断文件参数是否为空
		if (StringUtils.isEmpty(remotePath)) {
			logger.error("FTP待下载文件路径为空...");
			return false;
		}

		// 判断文件参数是否为空
		if (StringUtils.isEmpty(localPath)) {
			logger.error("本地存储路径为空...");
			return false;
		}

		// 验证FTP是否可用
		if (null == ftpClient || !ftpClient.isConnected()) {
			logger.error("ftpClient实例不可用...");
			return false;
		}

		try {
			// 切换FTP目录
			boolean isDirExist = ftpClient.changeWorkingDirectory(remotePath);
			if (!isDirExist) {
				logger.info("FTP当日目录未生成...");
				return false;
			}
			ftpClient.enterLocalPassiveMode();

			// 获取FTP文件
			FTPFile[] remoteFiles = ftpClient.listFiles();
			if (null == remoteFiles || remoteFiles.length < 1) {
				logger.info("FTP，路径：" + remotePath + "不存在文件...");
				return false;
			}

			// 判断路径是否存在
			File path = new File(localPath);
			if (!path.exists()) {
				logger.info("构建本地当日目录：" + path);
				path.mkdirs();
			}

			// 循环处理
			for (FTPFile remoteFile : remoteFiles) {
				if (!remoteFile.isFile())
					continue;

				String fileName = localPath + File.separator
						+ remoteFile.getName();
				// 构建本地文件
				File localFile = new File(fileName);
				if (localFile.exists()) {
					logger.info("文件：" + fileName + "已经存在！");
					continue;
				}

				// 输出流
				OutputStream output = null;
				try {
					// 构建输出流
					output = new FileOutputStream(localFile);
					// 文件传输
					ftpClient.retrieveFile(remoteFile.getName(), output);
					logger.info("成功下载文件：" + fileName);
				} finally {
					if (null != output)
						output.close();
				}
			}
		} catch (MalformedServerReplyException me) {// 捕获Could not parse passive
													// host information.
			logger.error("捕获MalformedServerReplyException，重连...");
			closeFTPClient(ftpClient);
			flag = false;
		} catch (Exception e) {
			logger.error(e);
			closeFTPClient(ftpClient);
			flag = false;
		}
		return flag;
	}

	public static void main(String[] args) throws Exception {
		// 获取当日日期
		String nowDate = DateUtil.getDateToStr(DateUtil.yyyyMMdd, new Date());

		List<String> remoteFileList = new ArrayList<String>();
		remoteFileList.add("zbs" + File.separator + nowDate + File.separator
				+ "test1.txt");
		// remoteFileList.add("zbs" + File.separator + nowDate + File.separator
		// + "test2.txt");

		FTPUtil.bathDownload(
				FTPUtil.getFTPClient("127.0.0.1", "wuban", "wuban"),
				remoteFileList, "zbs" + File.separator + nowDate);

		// FTPUtil.bathDownload(FTPUtil.getFTPClient(), "zbs" + File.separator +
		// nowDate, "zbs" + File.separator + nowDate);
	}
}
